--- 模块功能：MQTT客户端处理框架
-- @author openLuat
-- @module mqtt.mqttTask
-- @license MIT
-- @copyright openLuat
-- @release 2018.03.28
module(..., package.seeall)

require "misc"
require "mqtt"
require "mqttInMsgQuakeInfoRel"
require "mqttOutMsgQuakeRel"
require "nvm"
require "logGenerator"
require "log"
-- 初始化nvm获取配置参数
nvm.init("config.lua", true)
-- 参数初始化
local ready, uname_mqtt, pwd_mqtt, mqtthost, topic, eqrTopic, port,
      mqttClientId, enableVerify, mckParams, caParams = false, nvm.get(
                                                            "centerConfig")[7],
                                                        nvm.get("centerConfig")[8],
                                                        nvm.get("centerConfig")[10],
                                                        nvm.get("centerConfig")[11],
                                                        nvm.get("centerConfig")[12],
                                                        nvm.get("centerConfig")[14],
                                                        nvm.get("centerConfig")[6],
                                                        nvm.get("centerConfig")[21],
                                                        nvm.get("centerConfig")[23],
                                                        nvm.get("centerConfig")[24]

local mqttRClient

--- MQTT连接是否处于激活状态
-- @return 激活状态返回true，非激活状态返回false
-- @usage mqttTask.isReady()
function isReady() return ready end

-- 组装主题列表
local function assembleTopic()
    local topicList = {}
    local topicListearth, eqrTopicList = string.split(topic, ","),
                                         string.split(eqrTopic, ",")
    for i = 1, #topicListearth, 1 do
        log.info("预警主题"..i.."：",topicListearth[i])
         topicList[topicListearth[i]] = 0
         end
    for i = 1, #eqrTopicList, 1 do topicList[eqrTopicList[i]] = 0 end
    return topicList
end

function stringToBool(str)
    str = tostring(str)
    return (str == "true")
end
local function getSystemTime()
    local tClock, nowDate = os.date("*t")
    nowDate = string.format("%04d-%02d-%02d %02d:%02d:%02d", tClock.year,
                            tClock.month, tClock.day, tClock.hour, tClock.min,
                            tClock.sec)
    return nowDate
end
-- if FlagMqttConnect==nil or FlagMqttConnect==true then
--     FlagMqttConnect=false
--     nvm.sett("securityConfig", 7, tostring(FlagMqttConnect), "SVR")
-- end
-- FlagMqttConnect=stringToBool(nvm.get("securityConfig")[7])
-- TokenData = nvm.get("securityConfig")[5]
local mqttTokenConnectFailCount, tokenGetCount = 0, 0
-- 密码登录
local function passwordLogin()
    local retryConnectCnt, retryStartDevCnt, topicSubscriptionFailCnt,
          topicSubscriptionSusCnt, logInfo, errorInfo, sysTime = 0, 0, 0, 0, "",
                                                                 "", ""
    local mqttPClient, mqtthostArray, host, transport = mqtt.client(
                                                            mqttClientId, 120,
                                                            uname_mqtt,
                                                            pwd_mqtt, nil, nil,
                                                            "3.1.1"),
                                                        string.split(mqtthost,
                                                                     "://")
    mqttRClient = mqttPClient
    host = mqtthostArray[1]
    transport = mqtthostArray[2]
    log.info("host", host, "transport", transport)
    if mqttRClient:connect(transport, tonumber(port), host) then
        -- if mqttRClient:connect(host, tonumber(port), transport) then
        log.info("password connect host success.")
        sysTime = getSystemTime()
        logInfo = ""
        if topicSubscriptionFailCnt < 1 and topicSubscriptionSusCnt < 1 then
            logInfo = "[" .. sysTime .. "]" ..
                          "[注册中心mq连接成功！]\n" .. "[mq信息:]" ..
                          "mqHost:" .. host .. ",mqTransport:" .. transport ..
                          ",mq用户名:" .. uname_mqtt .. "mq登录密码:" ..
                          pwd_mqtt .. "\n"
            logGenerator.generateLogTask(logInfo, "log")
        end
        retryConnectCnt = 0
        ready = true
        -- 订阅主题
        if mqttRClient:subscribe(assembleTopic()) then
            topicSubscriptionFailCnt = 0
            if topicSubscriptionSusCnt < 1 then
                logInfo = ""
                logInfo = "[" .. sysTime .. "]" ..
                              "[注册中心mq主题订阅成功！]\n" ..
                              "[主题信息:]" .. "topic:" .. topic ..
                              "[速报主题信息:]" .. "eqrTopic:" .. eqrTopic ..
                              "\n"
                logGenerator.generateLogTask(logInfo, "log")
            end
            topicSubscriptionSusCnt = topicSubscriptionSusCnt + 1
            -- 循环处理接收和发送的数据
            while true do
                if not mqttInMsgQuakeInfoRel.proc(mqttRClient) then
                    log.error("mqttInMsgQuakeInfoRel.mqttInMsg.proc error")
                    break
                end
                if not mqttOutMsgQuakeRel.proc(mqttRClient) then
                    log.error("mqttOutMsgQuakeRel.mqttOutnMsg.proc error")
                    break
                end
            end
        else
            topicSubscriptionSusCnt = 0
            if topicSubscriptionFailCnt < 1 then
                logInfo = "[" .. sysTime .. "]" ..
                              "[注册中心mq主题订阅失败！]\n"
                logGenerator.generateLogTask(logInfo, "log")
            end
            topicSubscriptionFailCnt = topicSubscriptionFailCnt + 1
        end
        ready = false
    else
        retryConnectCnt = retryConnectCnt + 1
        log.info("password connect host failure with retry count:",
                 retryConnectCnt)
    end
end
-- token登录
local function passwordToken()
    local logInfo, sysTime, topicSubFailCnt, topicSubSusCnt = "", "", 0, 0
    sysTime = string.format("%04d-%02d-%02d %02d:%02d:%02d", os.date("*t").year,
                            os.date("*t").month, os.date("*t").day,
                            os.date("*t").hour, os.date("*t").min,
                            os.date("*t").sec)
    log.info("mqttclientinfo:", mqttClientId, uname_mqtt)
    if mqttTokenConnectFailCount < 10 then
        log.info("try to connect host by token.")
        sys.waitUntil("GENERATE_TOKEN_DONE", 3000)
        TokenData = nvm.get("securityConfig")[5]
        testpwd_mqtt = TokenData
        log.info("TokenData:",TokenData)

        local mqttTokenClient, mqtthostArray, host, transport = mqtt.client(
                                                                    mqttClientId,
                                                                    120,
                                                                    uname_mqtt,
                                                                    testpwd_mqtt,
                                                                    nil, {
                qos = 0,
                retain = 0,
                topic = "/willTopic",
                payload = "willMessage"
            }, "3.1.1"), string.split(mqtthost, "://")

        mqttRClient = mqttTokenClient
        host = mqtthostArray[2]
        transport = mqtthostArray[1]
        log.info("host:", host, "transport:", transport, "port:", port)
        -- us private host
        -- host = "148.135.118.201"
        -- testport = "1883"
        -- host="tcp://120.205.5.245"
        -- testport="21883"
        transport = "tcp"
        FlagMqttConnect = stringToBool(nvm.get("securityConfig")[7])
        log.info("mqtt connect 1:", FlagMqttConnect)
        if mqttTokenClient:connect(host, tonumber(port), transport) then
            log.info("token connect host success.")
            LogInfo = ""
            FlagMqttConnect = true
            sys.publish("TOKEN_LOGIN_TRIED_SUCCESS")
            mqttTokenConnectFailCount = 0
            nvm.sett("securityConfig", 7, tostring(FlagMqttConnect), "SVR")
            log.info("FlagMqttConnect1:", FlagMqttConnect)

            logInfo = "[" .. sysTime .. "]" .. "[使用token登录成功！]\n"
            logGenerator.generateLogTask(logInfo, "log")
            -- 订阅主题
            if mqttTokenClient:subscribe(assembleTopic()) then
                sysTime = string.format("%04d-%02d-%02d %02d:%02d:%02d",
                                        os.date("*t").year, os.date("*t").month,
                                        os.date("*t").day, os.date("*t").hour,
                                        os.date("*t").min, os.date("*t").sec)
                topicSubFailCnt = 0
                if topicSubSusCnt < 1 then
                    logInfo = ""
                    logInfo = "[" .. sysTime .. "]" ..
                                  "[使用token登录mq主题订阅成功！]\n" ..
                                  "[主题信息:]" .. "topic:" .. topic .. "\n"
                    logGenerator.generateLogTask(logInfo, "log")
                end
                topicSubSusCnt = topicSubSusCnt + 1
                -- 循环处理接收和发送的数据
                while true do
                    if not mqttInMsgQuakeInfoRel.proc(mqttTokenClient) then
                        log.error("mqttInMsgQuakeInfoRel.mqttInMsg.proc error")
                        break
                    end
                    if not mqttOutMsgQuakeRel.proc(mqttTokenClient) then
                        log.error("mqttOutMsgQuakeRel.mqttOutnMsg.proc error")
                        break
                    end
                end
            else
                sysTime = string.format("%04d-%02d-%02d %02d:%02d:%02d",
                                        os.date("*t").year, os.date("*t").month,
                                        os.date("*t").day, os.date("*t").hour,
                                        os.date("*t").min, os.date("*t").sec)
                topicSubSusCnt = 0
                if topicSubFailCnt < 1 then
                    logInfo = "[" .. sysTime .. "]" ..
                                  "[使用token登录mq主题订阅失败！]\n"
                    logGenerator.generateLogTask(logInfo, "log")
                end
                topicSubFailCnt = topicSubFailCnt + 1
            end
        else
            FlagMqttConnect = false
            sys.publish("TOKEN_LOGIN_TRIED_FAIL")
            mqttTokenConnectFailCount = mqttTokenConnectFailCount + 1
            log.info("token connect host failure with failure count:",
                     mqttTokenConnectFailCount)
            logInfo = "[" .. sysTime .. "]" .. "[使用token登录失败！]\n"
            nvm.sett("securityConfig", 7, tostring(FlagMqttConnect), "SVR")
            log.info("FlagMqttConnect2:", FlagMqttConnect)
        end
        sys.publish("TOKEN_TRIED")
    else
        logInfo = "[" .. sysTime .. "]" .. "[使用token登录失败！]\n"
        logGenerator.generateLogTask(logInfo, "log")
        passwordLogin()
    end

end
-- 启动MQTT客户端任务
function startMQTTClient(clientNo)
    sys.taskInit(function()
        local retryConnectCnt, retryStartDevCnt, logInfo, errorInfo, sysTime =
            0, 0, "", "", ""
        local topicSubFailCnt, topicSubSusCnt = 0, 0
        sysTime = string.format("%04d-%02d-%02d %02d:%02d:%02d",
                                os.date("*t").year, os.date("*t").month,
                                os.date("*t").day, os.date("*t").hour,
                                os.date("*t").min, os.date("*t").sec)
        while true do
            if rtos.get_fs_free_size() < 921600 then
                if rtos.remove_dir(logGenerator.LOG_DIR_PATH) then
                    logInfo = ""
                    logInfo = "[" .. sysTime .. "]" ..
                                  "[日志文件删除成功！]\n"
                    logGenerator.generateLogTask(logInfo, "log")
                else
                    errorInfo = ""
                    errorInfo = "[" .. sysTime .. "]" ..
                                    "[日志文件删除失败！]\n"
                    logGenerator.generateLogTask(errorInfo, "log")
                end
            end
            if not socket.isReady() then
                retryConnectCnt = 0
                -- 等待网络环境准备就绪，超时时间是5分钟
                sys.waitUntil("IP_READY_IND", 300000)
                retryStartDevCnt = retryStartDevCnt + 1
            end
            if socket.isReady() then
                retryStartDevCnt = 0
                -- 创建一个MQTT客户端
                log.info("clientNo", clientNo, "uname_mqtt", uname_mqtt,
                         "pwd_mqtt", pwd_mqtt)
                if enableVerify == "true" then
                    -- token登陆
                    passwordToken()
                else
                    -- 密码登录
                    passwordLogin()
                end

                -- 断开MQTT连接
                if mqttRClient ~= nil then
                    mqttRClient:disconnect()
                end
                if retryConnectCnt >= 5 then
                    link.shut()
                    retryConnectCnt = 0
                end
                sys.wait(5000)
            else
                -- 进入飞行模式，20秒之后，退出飞行模式
                net.switchFly(true)
                sys.wait(20000)
                net.switchFly(false)
            end
            if retryStartDevCnt >= 7 then
                retryStartDevCnt = 0
                sys.restart("重启设备!!!！")
            end
        end

        -- passwordToken()
    end)
end
